package site.wanjiahao.session.impl;

import io.netty.channel.Channel;
import site.wanjiahao.session.GroupSession;
import site.wanjiahao.session.SessionFactory;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class MemoryGroupSessionImpl implements GroupSession {

    // 一个组下的所有channel对象
    private static final Map<String, Set<Channel>> groups = new ConcurrentHashMap<>();

    // 保留当前组对应组名称
    private static final Map<Channel, String> channelGroupMapping = new ConcurrentHashMap<>();

    @Override
    public boolean createGroup(String gName) {
        // 单例创建组，使用双检查锁
        Set<Channel> channels = groups.get(gName);
        if (channels == null) {
            synchronized (this) {
                if (channels == null) {
                    channels = new HashSet<>();
                    groups.put(gName, channels);
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public synchronized Set<String> listMembers(String gName) {
        Set<Channel> channels = listChannel(gName);
        if (channels != null) {
            return channels.stream().map(item -> SessionFactory.getSession().getUsername(item)).collect(Collectors.toSet());
        }
        return null;
    }

    @Override
    public synchronized boolean join(String gName, Channel channel) {
        Set<Channel> channels = groups.get(gName);
        if (channels != null) {
            channels.add(channel);
            channelGroupMapping.put(channel, gName);
            return true;
        }
        return false;
    }

    @Override
    public synchronized boolean quit(String gName, Channel channel) {
        Set<Channel> channels = groups.get(gName);
        if (channels != null) {
            boolean remove = channels.remove(channel);
            if (remove) {
                channelGroupMapping.remove(channel);
            }
            return remove;
        }
        return false;
    }

    @Override
    public Set<String> listGroup() {
        return groups.keySet();
    }

    @Override
    public Set<Channel> listChannel(String gName) {
        return groups.get(gName);
    }

    @Override
    public String getGroupName(Channel channel) {
        return channelGroupMapping.get(channel);
    }
}
